package com.xjrsoft.module.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.exception.MyException;
import com.xjrsoft.common.page.PageInput;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.RedisUtil;
import com.xjrsoft.common.utils.VoToColumnUtil;
import com.xjrsoft.module.organization.entity.*;
import com.xjrsoft.module.organization.mapper.RoleMapper;
import com.xjrsoft.module.organization.mapper.UserPostRelationMapper;
import com.xjrsoft.module.organization.mapper.UserRoleRelationMapper;
import com.xjrsoft.module.organization.vo.UserRoleVo;
import com.xjrsoft.module.system.dto.UpdateExcelAuthDto;
import com.xjrsoft.module.system.entity.ExcelAuth;
import com.xjrsoft.module.system.entity.ExcelFile;
import com.xjrsoft.module.system.mapper.ExcelAuthMapper;
import com.xjrsoft.module.system.mapper.ExcelFileMapper;
import com.xjrsoft.module.system.service.IExcelAuthService;
import com.xjrsoft.module.system.service.IExcelFileService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xjrsoft.module.system.vo.ExcelAuthVo;
import com.xjrsoft.module.system.vo.ExcelFilePageVo;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 在线excel表 服务实现类
 * </p>
 *
 * @author hnyyzy
 * @since 2024-03-25
 */
@Service
@AllArgsConstructor
public class ExcelFileServiceImpl extends ServiceImpl<ExcelFileMapper, ExcelFile> implements IExcelFileService {

    private final IExcelAuthService excelAuthService;

    private final UserRoleRelationMapper userRoleRelationMapper;

    private final RoleMapper roleMapper;

    private final UserPostRelationMapper userPostRelationMapper;

    private RedisUtil redisUtil;


    @Override
    public PageOutput<ExcelFilePageVo> getPageList(PageInput dto) {

        List<ExcelFile> excelFileList = list(Wrappers.<ExcelFile>lambdaQuery().like(StrUtil.isNotBlank(dto.getKeyword()), ExcelFile::getFileName, dto.getKeyword()));

        //根据登录人id，查看是否有对应的excel权限
        long userId = StpUtil.getLoginIdAsLong();
        List<UserRoleRelation> relations = userRoleRelationMapper.selectList(Wrappers.lambdaQuery(UserRoleRelation.class)
                .eq(UserRoleRelation::getUserId, userId));

        List<Long> relationIds = relations.stream().map(UserRoleRelation::getRoleId).collect(Collectors.toList());

        List<Role> roleList = roleMapper.selectList(Wrappers.lambdaQuery(Role.class)
                .select(Role.class, x -> VoToColumnUtil.fieldsToColumns(UserRoleVo.class).contains(x.getColumn()))
                .in(relationIds.size() > 0, Role::getId, relationIds));

        List<Long> roleIdList = roleList.stream().map(Role::getId).collect(Collectors.toList());

        //如果不是超级管理员就进行权限过滤
        if (!roleIdList.contains(GlobalConstant.SUPER_ADMIN_ROLE_ID) && excelFileList.size() > 0) {
            //自己创建的文件，具有权限
            List<ExcelFile> userCreateFile = excelFileList.stream().filter(x -> x.getCreateUserId().equals(userId)).collect(Collectors.toList());
            //获取所有的权限数据
            List<ExcelAuth> excelAuthList = excelAuthService.list();

            if (excelAuthList.size() > 0) {
                //用户所具有的岗位
                List<UserPostRelation> postRelations = userPostRelationMapper.selectList(Wrappers.lambdaQuery(UserPostRelation.class).eq(UserPostRelation::getUserId, userId));

                List<Long> postIdList = postRelations.stream().map(UserPostRelation::getPostId).collect(Collectors.toList());

                //根据用户id、角色id、岗位id查询当前登录人所具有的所有excel权限
                List<Long> excelIds = excelAuthList.stream().filter(x -> x.getObjectId().equals(userId)
                        || roleIdList.contains(x.getObjectId()) || postIdList.contains(x.getObjectId())).map(ExcelAuth::getExcelId).collect(Collectors.toList());

                if (excelIds.size() > 0) {//权限过滤，一个都没有就置空
                    excelFileList = excelFileList.stream().filter(x -> excelIds.contains(x.getId())).collect(Collectors.toList());
                } else {
                    excelFileList = new ArrayList<>();//置空
                }
            } else {
                excelFileList = new ArrayList<>();//置空
            }
            //自己创建的文件，具有权限
            if (userCreateFile.size() > 0){
                excelFileList.addAll(userCreateFile);
            }
        }


        List<ExcelFilePageVo> excelFilePageVoList = new ArrayList<>();
        if (excelFileList.size() > 0) {
            List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
            });
            for (ExcelFile excelFile : excelFileList) {
                ExcelFilePageVo excelFilePageVo = new ExcelFilePageVo();
                excelFilePageVo.setId(excelFile.getId());
                excelFilePageVo.setFileName(excelFile.getFileName());
                excelFilePageVo.setFileSize(excelFile.getFileSize());
                excelFilePageVo.setRemark(excelFile.getRemark());
                User user = userList.stream().filter(x -> x.getId().equals(excelFile.getCreateUserId())).findFirst().orElse(new User());
                excelFilePageVo.setCreateUserName(user.getName());
                if (ObjectUtil.isNotEmpty(excelFile.getModifyUserId())) {
                    excelFilePageVo.setModifyDate(excelFile.getModifyDate());
                } else {
                    excelFilePageVo.setModifyDate(excelFile.getCreateDate());
                }
                excelFilePageVoList.add(excelFilePageVo);
            }
        }

        if (excelFilePageVoList.size() > 0){
            excelFilePageVoList.sort((t1,t2)->t2.getModifyDate().compareTo(t1.getModifyDate()));
        }

        PageOutput<ExcelFilePageVo> output = new PageOutput<>();
        output.setCurrentPage(dto.getLimit());
        output.setPageSize(dto.getSize());
        output.setTotal(excelFileList.size());
        output.setList(excelFilePageVoList);
        return output;
    }

    @Override
    public Boolean deleteExcel(List<Long> ids) {
        //删除excel数据
        removeBatchByIds(ids);
        //删除对应的权限数据
        return excelAuthService.remove(Wrappers.<ExcelAuth>lambdaQuery().in(ExcelAuth::getExcelId,ids));
    }

    @Override
    public Boolean updateExcelAuth(UpdateExcelAuthDto dto) {
        //先全部删除
        excelAuthService.remove(Wrappers.<ExcelAuth>lambdaQuery().eq(ExcelAuth::getExcelId, dto.getExcelId()));
        //然后再新增
        if (dto.getExcelAuthDtoList().size() > 0) {
            List<ExcelAuth> excelAuths = BeanUtil.copyToList(dto.getExcelAuthDtoList(), ExcelAuth.class);
            for (ExcelAuth excelAuth : excelAuths) {
                excelAuth.setExcelId(dto.getExcelId());
            }
            excelAuthService.saveBatch(excelAuths);
        }
        return true;
    }

    @Override
    public List<ExcelAuthVo> excelAuthInfo(Long id) {
        List<ExcelAuth> excelAuths = excelAuthService.list((Wrappers.<ExcelAuth>lambdaQuery().eq(ExcelAuth::getExcelId, id)));
        List<ExcelAuthVo> excelAuthVoList = new ArrayList<>();
        if (excelAuths.size() > 0) {
            for (ExcelAuth excelAuth : excelAuths) {
                ExcelAuthVo excelAuthVo = BeanUtil.toBean(excelAuth, ExcelAuthVo.class);
                if (excelAuth.getAuthType() == 0){
                    excelAuthVo.setAuthTypeName("用户");
                    //用户名称
                    List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
                    });
                    User user = userList.stream().filter(x -> x.getId().equals(excelAuth.getObjectId())).findFirst().orElse(new User());
                    excelAuthVo.setObjectName(user.getName());
                }else if (excelAuth.getAuthType() == 1){
                    excelAuthVo.setAuthTypeName("角色");
                    //角色名称
                    List<Role> roleList = redisUtil.get(GlobalConstant.ROLE_CACHE_KEY, new TypeReference<List<Role>>() {
                    });
                    Role role = roleList.stream().filter(x -> x.getId().equals(excelAuth.getObjectId())).findFirst().orElse(new Role());
                    excelAuthVo.setObjectName(role.getName());
                }else {
                    excelAuthVo.setAuthTypeName("岗位");
                    //岗位名称
                    List<Post> postList = redisUtil.get(GlobalConstant.POST_CACHE_KEY, new TypeReference<List<Post>>() {
                    });
                    Post post = postList.stream().filter(x -> x.getId().equals(excelAuth.getObjectId())).findFirst().orElse(new Post());
                    excelAuthVo.setObjectName(post.getName());
                }
                excelAuthVoList.add(excelAuthVo);
            }
        }
        return excelAuthVoList;
    }
}
